﻿// ---------------------------------------------------------------------------------------------------------------------
//   Copyright (c) SRT Solutions 2009. All rights reserved.
// ---------------------------------------------------------------------------------------------------------------------
using System;

namespace SRTSolutions.Elevate
{
    using global::System;

    /// <summary>
    /// Contains extension methods for the Option type.
    /// </summary>
    public static class OptionExtensions
    {
        /// <summary>
        /// If the input has a value, applies the selector function on the value and returns the result.
        /// Otherwise returns None.
        /// </summary>
        /// <typeparam name="T">The input type.</typeparam>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="input">The input value.</param>
        /// <param name="selector">The selector function.</param>
        /// <returns></returns>
        public static Option<TResult> Select<T, TResult>(this Option<T> input, Func<T, Option<TResult>> selector)
        {
            if (input == null)
                throw new ArgumentNullException("input", "input is null.");
            if (selector == null)
                throw new ArgumentNullException("selector", "selector is null.");

            return input.IsNone ? Option<TResult>.None : selector(input.Value);
        }

        /// <summary>
        /// If the option type is Some, returns the value otherwise returns
        /// the default value provided.
        /// </summary>
        /// <typeparam name="T">The type of the option.</typeparam>
        /// <param name="input">The input option.</param>
        /// <param name="defaultValue">
        /// The default value to return if the option is None.
        /// </param>
        /// <returns>
        /// The value of the option if it is Some otherwise the default value.
        /// </returns>
        public static T GetValueOrDefaultTo<T>(this Option<T> input, T defaultValue)
        {
            if (input == null)
                throw new ArgumentNullException("input", "input is null.");
            if (defaultValue == null)
                throw new ArgumentNullException("defaultValue", "defaultValue is null.");

            return input.IsSome ? input.Value : defaultValue;
        }
    }
}
